package com.edgar.plugin.hooks;

import android.content.ComponentName;
import android.content.Context;

import com.edgar.plugin.PluginManager;
import com.edgar.plugin.SystemClassHolder;
import com.edgar.plugin.pm.Plugin;
import com.edgar.plugin.utils.FieldUtils;
import com.edgar.plugin.utils.MethodUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * Created by Edgar on 2018/2/12.
 */
public class PackageManagerHook extends Hook{

    private PluginManager mPluginManager;
    public PackageManagerHook(Context context) {
        super(context);
        mPluginManager = PluginManager.getInstance();
    }

    @Override
    protected void onInstall(Context context) {
        super.onInstall(context);
        Class<?> c_activityThread = SystemClassHolder.activityThreadClass();
        Object oldObject = MethodUtils.invokeStaticMethod(c_activityThread,"getPackageManager",null);
        setOldObject(oldObject);
        Object proxy = Proxy.newProxyInstance(context.getClassLoader(),
                new Class[]{SystemClassHolder.packageManagerClass()},this);
        FieldUtils.writeStaticField(c_activityThread,"sPackageManager",proxy);
    }

    @Override
    protected void onInitHookMethodHandle(Map<String, HookMethodHandle> hookMethodHandles) {
        super.onInitHookMethodHandle(hookMethodHandles);
        hookMethodHandles.put("getPackageInfo",new getPackageInfo());
        hookMethodHandles.put("getActivityInfo",new getActivityInfo());
    }

    private class getActivityInfo extends HookMethodHandle{
        @Override
        Object onInvoke(Object receiver, Method method, Object[] args) throws Throwable {
            ComponentName componentName = (ComponentName) args[0];
            if (mPluginManager.isPlugin(componentName.getPackageName())){
                return mPluginManager.getActivityInfo(componentName);
            }
            return super.onInvoke(receiver, method, args);
        }
    }

    private class getPackageInfo extends HookMethodHandle{

        @Override
        Object onInvoke(Object receiver, Method method, Object[] args) throws Throwable {
            String packageName = (String) args[0];
            if (mPluginManager.isPlugin(packageName)){
                Plugin plugin = mPluginManager.getPlugin(packageName);
                return getContext().getPackageManager().getPackageArchiveInfo(plugin.getApplicationInfo().sourceDir,0);
            }
            return super.onInvoke(receiver, method, args);
        }
    }
}
